use std::{sync::Arc, time::Duration};

use crate::error::*;
use serde::{Deserialize, Serialize};

pub use h2::server::Builder as H2Builder;

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(default)]
pub struct H2ServerConf {
    // Setting配置.
    pub max_concurrent_streams: Option<usize>,

    pub max_frame_size: Option<usize>,

    pub max_header_list_size: Option<usize>,

    // pub header_table_size: Option<usize>,
    pub initial_window_size: Option<usize>,

    // h2 builder conf
    pub reset_stream_ms: Option<usize>,

    pub reset_stream_max: Option<usize>,

    pub pending_accept_reset_stream_max: Option<usize>,

    pub initial_target_connection_window_size: Option<usize>,

    pub max_send_buffer_size: Option<usize>,

    pub local_max_error_reset_streams: Option<usize>,
}

#[allow(dead_code)]
impl H2ServerConf {
    pub fn to_runtime_conf(
        &self,
        pre_conf: Option<&Arc<H2ServerRuntimeConf>>,
    ) -> Result<Arc<H2ServerRuntimeConf>> {
        let def_max_concurrent_streams;
        let def_max_frame_size;
        let def_max_header_list_size;
        // let def_header_table_size;
        let def_initial_window_size;
        let def_reset_stream_ms;
        let def_reset_stream_max;
        let def_pending_accept_reset_stream_max;
        let def_initial_target_connection_window_size;
        let def_max_send_buffer_size;
        let def_local_max_error_reset_streams;

        match pre_conf {
            Some(pre_conf) => {
                def_max_concurrent_streams =
                    pre_conf.h2_server_conf.max_concurrent_streams;
                def_max_frame_size = pre_conf.h2_server_conf.max_frame_size;
                def_max_header_list_size =
                    pre_conf.h2_server_conf.max_header_list_size;
                // def_header_table_size = pre_conf.h2_server_conf.header_table_size;
                def_initial_window_size =
                    pre_conf.h2_server_conf.initial_window_size;
                def_reset_stream_ms = pre_conf.h2_server_conf.reset_stream_ms;
                def_reset_stream_max = pre_conf.h2_server_conf.reset_stream_max;
                def_pending_accept_reset_stream_max =
                    pre_conf.h2_server_conf.pending_accept_reset_stream_max;
                def_initial_target_connection_window_size = pre_conf
                    .h2_server_conf
                    .initial_target_connection_window_size;
                def_max_send_buffer_size =
                    pre_conf.h2_server_conf.max_send_buffer_size;
                def_local_max_error_reset_streams =
                    pre_conf.h2_server_conf.local_max_error_reset_streams;
            }

            None => {
                def_max_concurrent_streams = None;
                def_max_frame_size = None;
                def_max_header_list_size = None;
                // def_header_table_size = None;
                def_initial_window_size = None;
                def_reset_stream_ms = None;
                def_reset_stream_max = None;
                def_pending_accept_reset_stream_max = None;
                def_initial_target_connection_window_size = None;
                def_max_send_buffer_size = None;
                def_local_max_error_reset_streams = None;
            }
        }

        let max_concurrent_streams =
            self.max_concurrent_streams.or(def_max_concurrent_streams);
        let max_frame_size = self.max_frame_size.or(def_max_frame_size);
        let max_header_list_size =
            self.max_header_list_size.or(def_max_header_list_size);
        // let header_table_size = self.header_table_size.or(def_header_table_size);
        let initial_window_size =
            self.initial_window_size.or(def_initial_window_size);
        let reset_stream_ms = self.reset_stream_ms.or(def_reset_stream_ms);
        let reset_stream_max = self.reset_stream_max.or(def_reset_stream_max);
        let pending_accept_reset_stream_max = self
            .pending_accept_reset_stream_max
            .or(def_pending_accept_reset_stream_max);
        let initial_target_connection_window_size = self
            .initial_target_connection_window_size
            .or(def_initial_target_connection_window_size);
        let max_send_buffer_size =
            self.max_send_buffer_size.or(def_max_send_buffer_size);
        let local_max_error_reset_streams = self
            .local_max_error_reset_streams
            .or(def_local_max_error_reset_streams);

        let mut h2_server_builder = H2Builder::default();
        if let Some(value) = max_concurrent_streams {
            h2_server_builder.max_concurrent_streams(value as u32);
        }
        if let Some(value) = max_frame_size {
            h2_server_builder.max_frame_size(value as u32);
        }
        if let Some(value) = max_header_list_size {
            h2_server_builder.max_header_list_size(value as u32);
        }
        // h2库未开放该配置.
        // if let Some(value) = header_table_size {}
        if let Some(value) = initial_window_size {
            h2_server_builder.initial_window_size(value as u32);
        }
        if let Some(value) = reset_stream_ms {
            h2_server_builder
                .reset_stream_duration(Duration::from_millis(value as u64));
        }
        if let Some(value) = reset_stream_max {
            h2_server_builder.max_concurrent_reset_streams(value);
        }
        if let Some(value) = pending_accept_reset_stream_max {
            h2_server_builder.max_pending_accept_reset_streams(value);
        }
        if let Some(value) = initial_target_connection_window_size {
            h2_server_builder.initial_connection_window_size(value as u32);
        }
        if let Some(value) = max_send_buffer_size {
            h2_server_builder.max_send_buffer_size(value);
        }
        h2_server_builder
            .max_local_error_reset_streams(local_max_error_reset_streams);

        Ok(Arc::new(
            H2ServerRuntimeConf {
                h2_server_conf: H2ServerConf {
                    max_concurrent_streams,
                    max_frame_size,
                    max_header_list_size,
                    // header_table_size,
                    initial_window_size,
                    reset_stream_ms,
                    reset_stream_max,
                    pending_accept_reset_stream_max,
                    initial_target_connection_window_size,
                    max_send_buffer_size,
                    local_max_error_reset_streams,
                },
                h2_server_builder,
            }
            .valid()?,
        ))
    }
}

#[allow(dead_code)]
pub struct H2ServerRuntimeConf {
    pub h2_server_conf: H2ServerConf,
    pub h2_server_builder: H2Builder,
}

#[allow(dead_code)]
impl H2ServerRuntimeConf {
    fn valid(self) -> Result<Self> {
        Ok(self)
    }
}
